package base

import (
	"gitee.com/ymofen/gobase"
	"sync"
)

type ConverterWrapper struct {
	c             DataConverter
	ctype         string
	s             string
	lk            sync.RWMutex
	converterFunc func(buf []byte) (newBuf []byte, err error)
	warn          string
}

func nullInputBuf(buf []byte) (newBuf []byte, err error) {
	return buf, nil
}

func NewConverterWrapper() *ConverterWrapper {
	rval := &ConverterWrapper{converterFunc: nullInputBuf}
	return rval
}

func (this *ConverterWrapper) GetStatus(args ...interface{}) string {
	this.lk.RLock()
	defer this.lk.RUnlock()
	if this.c == nil {
		return this.warn
	} else {
		return TryGetStatus(this.c, args...)
	}
}

func (this *ConverterWrapper) InputBuf(buf []byte) (newBuf []byte, err error) {
	this.lk.RLock()
	defer this.lk.RUnlock()
	return this.converterFunc(buf)
}

func (this *ConverterWrapper) Close() error {
	this.lk.Lock()
	defer this.lk.Unlock()
	if this.c != nil {
		_, err := TryClose(this.c)
		this.c = nil
		this.warn = "closed"
		return err
	}
	return nil
}

func (this *ConverterWrapper) UpdateConf(s string) error {
	this.lk.Lock()
	defer this.lk.Unlock()
	if s != this.s {
		this.s = s
		confMap := gobase.NewStrMap()
		confMap.URLFormDecode(s)
		ctype := confMap.StringByName("type", "")
		if this.c != nil {
			if this.ctype == ctype {
				this.c.UpdateConf(confMap)
				return nil
			}
			TryClose(this.c)
			this.c = nil
			this.converterFunc = nullInputBuf
			this.ctype = ""
		}

		if len(ctype) != 0 {
			c, err := CreateDataConverterEx(confMap)
			if err != nil {
				this.warn = err.Error()
				return err
			} else {
				this.c = c
				this.ctype = ctype
				this.warn = ""
				this.converterFunc = c.InputBuf
				return nil
			}
		}
	}
	return nil

}
